package com.codi.bus.core.service.impl;

import com.codi.base.util.ExceptionUtil;
import com.codi.base.util.StringUtil;
import com.codi.bus.constant.GlobalConstant;
import com.codi.bus.constant.RuleConstant;
import com.codi.bus.core.dao.LookupDao;
import com.codi.bus.core.dao.UserDao;
import com.codi.bus.core.domain.Lookup;
import com.codi.bus.core.domain.User;
import com.codi.bus.core.resultModel.DividendApplyResult;
import com.codi.bus.core.resultModel.FundNetValueResult;
import com.codi.bus.core.service.DividendApplyService;
import com.codi.bus.core.service.FundDetailService;
import com.codi.bus.core.service.model.DividendModel;
import com.codi.bus.core.service.util.CodeUtils;
import com.codi.bus.core.service.util.HundsunUtils;
import com.codi.bus.core.service.util.ModelPopulateUtils;
import com.codi.bus.exception.BaseException;
import com.codi.bus.exception.SystemDBException;
import com.codi.message.constant.ErrorConstant;
import com.codi.trade.dto.HsDividendQryDto;
import com.codi.trade.service.DividendsQueryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by asus on 2018/3/16.
 */
@Slf4j
@Service("dividendApplyService")
@Transactional
public class DividendApplyServiceImpl implements DividendApplyService {
    @Autowired
    private UserDao userDao;

    @Autowired
    private DividendsQueryService dividendsQueryService;

    @Autowired
    private LookupDao lookupDao;

    @Autowired
    private FundDetailService fundDetailService;


    /**
     * 组合分红交易记录
     *
     * @param userId
     * @param requestNum
     * @param queryFlag
     * @param beginNum
     * @param sortDirection
     * @return
     * @throws BaseException
     */
    @Override
    public DividendApplyResult queryPortfolioDividendApplys(Long userId, Integer requestNum, Integer queryFlag, Integer beginNum,
                                                            String sortDirection,String taSerialId) throws BaseException {
        log.info("queryApplys - userId=" + userId);

        DividendApplyResult result = new DividendApplyResult();
        try {

            // 获取用户
            User user = userDao.getEntity(userId);
            // 判断是否已开户
            if (user == null || StringUtil.isEmpty(user.getExternalClientId())) {
                result.setSuccess(false);
                result.setErrorCode(ErrorConstant.ERROR_NO_ACCOUNT);
                result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
                return result;
            }
            HsDividendQryDto hsDividendQryDto;
            if (StringUtils.isNotBlank(taSerialId)){
                hsDividendQryDto = HsDividendQryDto.builder()
                    .client_id(user.getExternalClientId())
                    .sort_direction("1")
                    .qry_beginrownum(1)
                    .reqry_recordsum_flag("1")
                    .ta_serial_id(taSerialId)
                    .request_num(GlobalConstant.MAX_REQUEST_NUM)
                    .build();
            }else {
                hsDividendQryDto = HsDividendQryDto.builder()
                    .client_id(user.getExternalClientId())
                    .sort_direction("1")
                    .qry_beginrownum(1)
                    .reqry_recordsum_flag("1")
                    .request_num(GlobalConstant.MAX_REQUEST_NUM)
                    .build();
            }
            Map<String, Object> map = dividendsQueryService.queryDto(hsDividendQryDto);
            List<Map<String, Object>> list = new ArrayList<>();
            // 查询结果
            HundsunUtils.ConvertToList(map, list, result);
            if (!result.getSuccess()) {
                return result;
            }

            // 银行名称
            List<Lookup> bankLookups = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_HSBANK);
            // populate

            List<DividendModel> dividendModels1 = ModelPopulateUtils.populateDividend(list, result);
            List<DividendModel> dividendModels = new ArrayList<>();


            List<String> fundCodeList = new ArrayList<String>();
            for (DividendModel dividendModel : dividendModels1) {
                if (!dividendModel.getTradeAccount().startsWith("ZH")) {
                    continue;
                }
                // 设置银行名称
                if (bankLookups != null) {
                    for (Lookup lookup : bankLookups) {
                        if (lookup.getRuleValue().equals(dividendModel.getBangNo())) {
                            dividendModel.setBankName(lookup.getRuleText());
                            break;
                        }
                    }
                }
                // 从聚源获取基金信息
                if (!fundCodeList.contains(dividendModel.getFundCode())) {
                    fundCodeList.add(dividendModel.getFundCode());
                }
                dividendModels.add(dividendModel);
            }

            List<FundNetValueResult> fundNetValueList = null;
            try {
                fundNetValueList = fundDetailService.getFundNetValueByBatch(fundCodeList, new Date());
            } catch (Exception ex) {
                result.setSuccess(false);
                result.setErrorType(GlobalConstant.ERROR_TYPE_SYSTEM);
                ExceptionUtil.logError(log, "queryApplys - fundDetailService - Exception:", ex);
                result.setErrorCode(ErrorConstant.ERROR_GILDATA_WRONG);
                return result;
            }

            // 如果没有找到聚源数据，则默认为空数组
            if (fundNetValueList == null) {
                fundNetValueList = new ArrayList<>();
            }

            for (DividendModel dividendModel : dividendModels) {
                // 设置基金信息
                for (FundNetValueResult fundNetValue : fundNetValueList) {
                    if (fundNetValue == null) {
                        continue;
                    }
                    if (fundNetValue.getFundCode().equals(dividendModel.getFundCode())) {
                        dividendModel.setFundName(fundNetValue.getChiNameAbbr());
                        break;
                    }
                }

            }


            Collections.sort(dividendModels, new Comparator<DividendModel>() {
                @Override
                public int compare(DividendModel o1, DividendModel o2) {
                    String o1No = o1.getDividendDate(), o2No = o2.getDividendDate();
                    if (o1No.length() < o2No.length()) {
                        return 1;
                    } else if (o1No.length() > o2No.length()) {
                        return -1;
                    }
                    return 0 - o1No.compareTo(o2No);
                }
            });

            result.setSuccess(true);
            result.setTotalCount((long) dividendModels.size());
            List<DividendModel> dividendReal = new ArrayList<>();
            for (int i = 1; i <= dividendModels.size(); i++) {
                if (i >= beginNum && i < requestNum + beginNum) {
                    dividendReal.add(dividendModels.get(i - 1));
                }
            }
            result.setDividendModels(dividendReal);

            return result;
        } catch (BaseException baseException) {
            throw baseException;
        } catch (Exception exception) {
            ExceptionUtil.logError(log, "queryApplys - Exception:", exception);
            throw new SystemDBException("queryApplys Failure!", exception);
        }
    }

    /*
     * 查询普通基金分红交易记录
     */
    @Override
    public DividendApplyResult queryNormalDividendApplys(Long userId, Integer requestNum, Integer queryFlag, Integer beginNum, String sortDirection,String taSerialId) throws BaseException {
        log.info("queryApplys - userId=" + userId);
        DividendApplyResult result = new DividendApplyResult();
        try {
            // 获取用户
            User user = userDao.getEntity(userId);

            // 判断是否已开户
            if (user == null || StringUtil.isEmpty(user.getExternalClientId())) {
                result.setSuccess(false);
                result.setErrorCode(ErrorConstant.ERROR_NO_ACCOUNT);
                result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
                return result;
            }


            HsDividendQryDto hsDividendQryDto;
            if (StringUtils.isNotBlank(taSerialId)){
                hsDividendQryDto = HsDividendQryDto.builder()
                    .client_id(user.getExternalClientId())
                    .sort_direction("1")
                    .qry_beginrownum(1)
                    .reqry_recordsum_flag("1")
                    .ta_serial_id(taSerialId)
                    .request_num(GlobalConstant.MAX_REQUEST_NUM)
                    .build();
            }else {
                hsDividendQryDto = HsDividendQryDto.builder()
                    .client_id(user.getExternalClientId())
                    .sort_direction("1")
                    .qry_beginrownum(1)
                    .reqry_recordsum_flag("1")
                    .request_num(GlobalConstant.MAX_REQUEST_NUM)
                    .build();
            }
            Map<String, Object> map = dividendsQueryService.queryDto(hsDividendQryDto);
            List<Map<String, Object>> list = new ArrayList<>();
            // 查询结果
            HundsunUtils.ConvertToList(map, list, result);
            if (!result.getSuccess()) {
                return result;
            }
            // 银行名称
            List<Lookup> bankLookups = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_HSBANK);

            // populate
            List<DividendModel> dividendModelList = ModelPopulateUtils.populateDividend(list, result);
            List<DividendModel> dividendModels = new ArrayList<>();
            // 把T0基金过滤掉，因为T0基金有专门的页面来显示
            filterT0(dividendModelList, true);
            //过滤组合基金记录
            dividendModelList.forEach(dividendModel -> {
                if (!dividendModel.getTradeAccount().startsWith("ZH")) {
                    dividendModels.add(dividendModel);
                }
            });

            List<String> fundCodeList = new ArrayList<String>();
            for (DividendModel dividendModel : dividendModels) {
                // 设置银行名称
                if (bankLookups != null) {
                    for (Lookup lookup : bankLookups) {
                        if (lookup.getRuleValue().equals(dividendModel.getBangNo())) {
                            dividendModel.setBankName(lookup.getRuleText());
                            break;
                        }
                    }
                }
                // 从聚源获取基金信息
                if (!fundCodeList.contains(dividendModel.getFundCode())) {
                    fundCodeList.add(dividendModel.getFundCode());
                }
            }
            List<FundNetValueResult> fundNetValueList = null;
            try {
                fundNetValueList = fundDetailService.getFundNetValueByBatch(fundCodeList, new Date());
            } catch (Exception ex) {
                result.setSuccess(false);
                ExceptionUtil.logError(log, "queryApplys - fundDetailService - Exception:", ex);
                result.setErrorType(GlobalConstant.ERROR_TYPE_SYSTEM);
                result.setErrorCode(ErrorConstant.ERROR_GILDATA_WRONG);
                return result;
            }
            // 如果没有找到聚源数据，则默认为空数组
            if (fundNetValueList == null) {
                fundNetValueList = new ArrayList<>();
            }
            for (DividendModel dividendModel : dividendModels) {
                // 设置基金信息
                for (FundNetValueResult fundNetValue : fundNetValueList) {
                    if (fundNetValue == null) {
                        continue;
                    }
                    if (fundNetValue.getFundCode().equals(dividendModel.getFundCode())) {
                        dividendModel.setFundName(fundNetValue.getChiNameAbbr());
                        break;
                    }
                }
            }
            CodeUtils.SortDividend(dividendModels);
            result.setSuccess(true);
            result.setTotalCount((long) dividendModels.size());
            List<DividendModel> dividendReal = new ArrayList<>();
            for (int i = 1; i <= dividendModels.size(); i++) {
                if (i >= beginNum && i < requestNum + beginNum) {
                    dividendReal.add(dividendModels.get(i - 1));
                }
            }
            result.setDividendModels(dividendReal);
            return result;
        } catch (BaseException baseException) {
            throw baseException;
        } catch (Exception exception) {
            ExceptionUtil.logError(log, "queryApplys - Exception:", exception);
            throw new SystemDBException("queryApplys Failure!", exception);
        }
    }

    @Override
    public void filterT0(List<DividendModel> dividendModels, boolean filterT0) {
        if (filterT0) {
            List<Lookup> T0Funds = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_T0FUND);
            Iterator<DividendModel> iterator = dividendModels.iterator();
            while (iterator.hasNext()) {
                DividendModel model = iterator.next();
                if (ModelPopulateUtils.isT0Fund(T0Funds, model.getFundCode())) {
                    iterator.remove();
                }
            }
        }
    }

    @Override
    public void filterFund(List<DividendModel> dividendModels, boolean filterT0) {
        if (filterT0) {
            List<Lookup> T0Funds = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_T0FUND);
            Iterator<DividendModel> iterator = dividendModels.iterator();
            while (iterator.hasNext()) {
                DividendModel model = iterator.next();
                if (!ModelPopulateUtils.isT0Fund(T0Funds, model.getFundCode())) {
                    iterator.remove();
                }
            }
        }
    }

    /*
     * 查询普通基金分红交易记录
     */
    @Override
    public DividendApplyResult queryWalletDividendApplys(Long userId, Integer requestNum, Integer queryFlag, Integer beginNum, String sortDirection,String taSerialId) throws BaseException {
        log.info("queryApplys - userId=" + userId);
        DividendApplyResult result = new DividendApplyResult();
        try {
            // 获取用户
            User user = userDao.getEntity(userId);
            // 判断是否已开户
            if (user == null || StringUtil.isEmpty(user.getExternalClientId())) {
                result.setSuccess(false);
                result.setErrorCode(ErrorConstant.ERROR_NO_ACCOUNT);
                result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
                return result;
            }
            HsDividendQryDto hsDividendQryDto;
            if (StringUtils.isNotBlank(taSerialId)){
                 hsDividendQryDto = HsDividendQryDto.builder()
                    .client_id(user.getExternalClientId())
                    .sort_direction("1")
                    .qry_beginrownum(1)
                    .reqry_recordsum_flag("1")
                    .ta_serial_id(taSerialId)
                    .request_num(GlobalConstant.MAX_REQUEST_NUM)
                    .build();
            }else {
                 hsDividendQryDto = HsDividendQryDto.builder()
                    .client_id(user.getExternalClientId())
                    .sort_direction("1")
                    .qry_beginrownum(1)
                    .reqry_recordsum_flag("1")
                    .request_num(GlobalConstant.MAX_REQUEST_NUM)
                    .build();
            }

            Map<String, Object> map = dividendsQueryService.queryDto(hsDividendQryDto);
            List<Map<String, Object>> list = new ArrayList<>();
            // 查询结果
            HundsunUtils.ConvertToList(map, list, result);
            if (!result.getSuccess()) {
                return result;
            }
            // 银行名称
            List<Lookup> bankLookups = lookupDao.getLookupByType(RuleConstant.RULE_LOOKUP_TYPE_HSBANK);

            // populate
            List<DividendModel> dividendModelList = ModelPopulateUtils.populateDividend(list, result);
            List<DividendModel> dividendModels = new ArrayList<>();
            // 把T0基金过滤掉，因为T0基金有专门的页面来显示
            filterFund(dividendModelList, true);
            //过滤组合基金记录
            dividendModelList.forEach(dividendModel -> {
                if (!dividendModel.getTradeAccount().startsWith("ZH")) {
                    dividendModels.add(dividendModel);
                }
            });

            List<String> fundCodeList = new ArrayList<String>();
            for (DividendModel dividendModel : dividendModels) {
                // 设置银行名称
                if (bankLookups != null) {
                    for (Lookup lookup : bankLookups) {
                        if (lookup.getRuleValue().equals(dividendModel.getBangNo())) {
                            dividendModel.setBankName(lookup.getRuleText());
                            break;
                        }
                    }
                }
                // 从聚源获取基金信息
                if (!fundCodeList.contains(dividendModel.getFundCode())) {
                    fundCodeList.add(dividendModel.getFundCode());
                }
            }
            List<FundNetValueResult> fundNetValueList = null;
            try {
                fundNetValueList = fundDetailService.getFundNetValueByBatch(fundCodeList, new Date());
            } catch (Exception ex) {
                result.setSuccess(false);
                ExceptionUtil.logError(log, "queryApplys - fundDetailService - Exception:", ex);
                result.setErrorType(GlobalConstant.ERROR_TYPE_SYSTEM);
                result.setErrorCode(ErrorConstant.ERROR_GILDATA_WRONG);
                return result;
            }
            // 如果没有找到聚源数据，则默认为空数组
            if (fundNetValueList == null) {
                fundNetValueList = new ArrayList<>();
            }
            for (DividendModel dividendModel : dividendModels) {
                // 设置基金信息
                for (FundNetValueResult fundNetValue : fundNetValueList) {
                    if (fundNetValue == null) {
                        continue;
                    }
                    if (fundNetValue.getFundCode().equals(dividendModel.getFundCode())) {
                        dividendModel.setFundName(fundNetValue.getChiNameAbbr());
                        break;
                    }
                }
            }
            CodeUtils.SortDividend(dividendModels);
            result.setSuccess(true);
            result.setTotalCount((long) dividendModels.size());
            List<DividendModel> dividendReal = new ArrayList<>();
            for (int i = 1; i <= dividendModels.size(); i++) {
                if (i >= beginNum && i < requestNum + beginNum) {
                    dividendReal.add(dividendModels.get(i - 1));
                }
            }
            result.setDividendModels(dividendReal);
            return result;
        } catch (BaseException baseException) {
            throw baseException;
        } catch (Exception exception) {
            ExceptionUtil.logError(log, "queryApplys - Exception:", exception);
            throw new SystemDBException("queryApplys Failure!", exception);
        }
    }
}
